/*
 * Copyright (c) 2006 Your Corporation. All Rights Reserved.
 */
package org.ivytools.repository.svn;

import fr.jayasoft.ivy.repository.Resource;
import fr.jayasoft.ivy.util.Message;
import org.tigris.subversion.svnclientadapter.*;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Represents a named resource in a subversion repository.
 *
 * @author shaug
 * @since Jan 18, 2006 8:56:58 AM
 */
public class SvnResource implements Resource {
    private ISVNClientAdapter client;
    private String source;
    private ISVNDirEntry info;
    private SVNUrl svnUrl;

    public SvnResource(ISVNClientAdapter client, String source) {
        this.client = client;
        this.source = source;
    }

    private void init() {
        if (info != null) {
            return;
        }
        try {
            svnUrl = new SVNUrl(source);
            if (svnUrl.getParent() == null) {
                info = new RootDirEntry();
            } else {
                try {
                    info = client.getDirEntry(svnUrl, SVNRevision.HEAD);
                } catch (SVNClientException e) {
                    throw new IllegalStateException("Error connecting to " + svnUrl, e);
                }
            }
        } catch (MalformedURLException e) {
            throw new IllegalStateException("Can't convert source to svn url: " + source, e);
        }
    }

    public String getName() {
        return source;
    }

    public long getLastModified() {
        init();
        return info == null ? 0 : info.getLastChangedDate().getTime();
    }

    public long getContentLength() {
        init();
        return info == null ? 0 : info.getSize();
    }

    public boolean exists() {
        return isDirectory() || isFile();
    }

    private boolean isDirectory() {
        init();
        String path = info.getPath();
        return (info != null && info.getNodeKind() == SVNNodeKind.DIR) ||
                path == null || path.equals("") || path.equals("/")
                ;
    }

    private boolean isFile() {
        init();
        return info != null && info.getNodeKind() == SVNNodeKind.FILE;
    }

    public InputStream getInputStream() throws IOException {
        init();
        Message.verbose("Retrieving file " + source);
        try {
            return client.getContent(svnUrl, SVNRevision.HEAD);
        } catch (SVNClientException e) {
            throw (IOException) new IOException("Unable to fetch file " + source).initCause(e);
        }
    }

    public List<String> getDirEntries() throws IOException {
        init();
        if (isFile()) {
            return null;
        }
        Message.verbose("Retrieving directory entries " + svnUrl);
        try {
            ISVNDirEntry[] list = client.getList(svnUrl, SVNRevision.HEAD, false);
            if (list == null || list.length == 0) {
                return Collections.emptyList();
            }
            List<String> dirEntries = new ArrayList<String>(list.length);
            for (ISVNDirEntry item : list) {
                dirEntries.add(item.getPath());
            }
            return dirEntries;
        } catch (SVNClientException e) {
            throw (IOException) new IOException("Unable to get directory entries for " + svnUrl).initCause(e);
        }
    }


    @Override
    public String toString() {
        return getName();
    }
}
